package game;

import globals.GlobalObjects;
import globals.GlobalParameters;
import globals.ObjectType;
import graphics.GraphicalObject;
import graphics.GraphicalUniverse;
import graphics.Skybox.SkyBox;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import common.Position3D;

import physics.Avatar;
import physics.GameObject;
import physics.Planet;
import physics.PortalEntrance;
import physics.Sun;
import physics.Collisions.Collision;

public class Universe  {

	static GraphicalUniverse grUniverse = new GraphicalUniverse();
	static Camera camera = new Camera();
	static Avatar avatar;

	public static ArrayList<GameObject> objects = new ArrayList<GameObject>();
	public static ArrayList<PortalEntrance> portals = new ArrayList<PortalEntrance>();



	static Map<GameObject, GraphicalObject> presentations = new HashMap<GameObject, GraphicalObject>();

	static Sun sun;
	private static ArrayList<GameObject> planets = new ArrayList<GameObject>();


	public Universe(){}

	public static void addGameObject(GameObject obj)	{

		if (objects.contains(obj))
			return;

		if (obj instanceof Sun){
			setSun(obj);
		}
		else if (obj instanceof Planet){
			planets.add((Planet)obj);
		}
		else if (obj instanceof PortalEntrance){
			portals.add((PortalEntrance)obj);
		}

		objects.add(obj);
	}



	public static Camera getCamera() {
		return camera;
	}

	public static void setCamera(Camera cam) {
		camera = cam;
	}

	//get clock tick
	public static void actionPerformed(ActionEvent event) {
			fireEvent(event);
	}

	//send clock tick to all physicalObjects 
	static private void fireEvent(ActionEvent event) {
		for (GameObject object: objects) {
			object.clockTicked(event);
		}

		for (int i = 0; i<objects.size(); i++) {
			GameObject object =  objects.get(i);
			if (object.moved() ){
				object.setMoved(false);
				for (GameObject bumpedInto : getCollisions(object) ){
					handleCollisions(object, bumpedInto);
				}
			}		
		}

		for (int i =0; i< objects.size(); i++) {
			GameObject object = objects.get(i); 
			if (!object.exists())
				removeObject(object);
		}
	}

	private static void handleCollisions(GameObject object,
			GameObject bumpedInto) {
		if (bumpedInto!= null){
			Collision c = new Collision(object, bumpedInto);

			object.impact(c);
			bumpedInto.impact(c);
			//bumpedInto.setMoved(false);
		}
	}

	private static ArrayList<GameObject> getCollisions(GameObject object){
		ArrayList<GameObject> collisions = new ArrayList<GameObject>();
		try {
			for (GameObject objOnPlanet :object.getPlanet().getObjectsOnPlanet()){
				if (objOnPlanet != object && object.bumpedInto(objOnPlanet)){
					collisions.add(objOnPlanet);
				}
			}
		}
		catch (Exception e) {
			return new ArrayList<GameObject>();
		}
		return collisions;
	}
	public static void removeObject(GameObject obj){
		obj.getPlanet().removeObjectFromPlanet(obj);
		GraphicalObject grObj = presentations.get(obj);
		objects.remove(obj);

	}


	public static GraphicalUniverse getGrUniverse() {
		return grUniverse;
	}
	public static void setSun(GameObject gameObj) {
		sun = (Sun) gameObj;
	}
	public static Sun getSun(){
		return sun;
	}

	public static void setAvatar(Avatar avatarobj) {
		avatar = avatarobj;
	}

	public static Avatar getAvatar() {
		return avatar;
	}

	
	public static void clearUniverseData(){
		planets.clear();
		portals.clear();
		planets.clear();
		presentations.clear();
		sun = null;
		grUniverse = new GraphicalUniverse();
	}
}
